/*
 *     This file is part of Mobile GPS Logger.
 *
 *     Mobile GPS Logger is free software: you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation, either version 3 of the
 *     License, or (at your option) any later version.
 *
 *     Mobile GPS Logger is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License v3 for more details.
 *
 *     You should have received a copy of the GNU General Public License v3
 *     along with Mobile GPS Logger. If not, see <http://www.gnu.org/licenses/>.
*/

package cx.ath.skyflyer.gpslog;

import cx.ath.skyflyer.gpslog.ui.Alert;
import cx.ath.skyflyer.gpslog.ui.BusyAlert;
import java.io.IOException;
import java.util.Vector;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.List;

/**
 *
 * @author Ahti Legonkov
 */
public class DeviceList implements DiscoveryListener, CommandListener {

    DeviceList(GpsLogMidlet midlet) {
        m_Midlet = midlet;
        m_Alert = new Alert(midlet);
        try {
            m_BtLogo = Image.createImage("/images/bt_logo_16.png");
        }
        catch (IOException ex) {
            // the jar file should contain the image!!
            // assert(false);
        }
    }

    //
    // Implementation of DiscoveryListener
    //

    public void deviceDiscovered(RemoteDevice device, DeviceClass cls) {
        try
        {
            m_Devices.append(device.getFriendlyName(true), m_BtLogo);
            m_DeviceVector.addElement(device);
        }
        catch (IOException ex)
        {
            m_Devices.append("(?)Device: " + ex.getMessage(), m_BtLogo);
            m_DeviceVector.addElement(device);
        }
    }

    public void inquiryCompleted(int discType) {

        Display disp = Display.getDisplay(m_Midlet);

        switch (discType) {
        case DiscoveryListener.INQUIRY_TERMINATED:
            // just show the empty list if the user terminates the search...
            
        case DiscoveryListener.INQUIRY_COMPLETED:
            disp.setCurrent(m_Devices);
            break;

        default:
            m_Alert.display("Inquiry error "+discType+".", AlertType.ERROR, 5000);
            break;
        }
    }

    public void serviceSearchCompleted(int arg0, int arg1) {
        throw new UnsupportedOperationException("Not supported.");
    }

    public void servicesDiscovered(int arg0, ServiceRecord[] arg1) {
        throw new UnsupportedOperationException("Not supported.");
    }

    //
    // Implementation of CommandListener
    //

    public void commandAction(Command c, Displayable d) {
        if (c == CMD_RETRY) {
            onCmdRetry();
        }
        else if (c == CMD_EXIT) {
            onCmdExit();
        }
        else if (c == CMD_CANCEL) {
            onCancelSearch();
        }
        else if (c == List.SELECT_COMMAND && d == m_Devices) {
            onListItemSelected((List)d);
        }
        else {
            // ... ?
        }
    }

    //
    // Private parts
    //

    /** A Command to retry scanning for devices. */
    private static final Command CMD_RETRY = new Command("Retry", Command.SCREEN, 1);

    /** A Command to exit the application. */
    private static final Command CMD_EXIT = new Command("Exit", Command.EXIT, 2);

    /** A Command to cancel the device discovery. */
    private static final Command CMD_CANCEL = new Command("Cancel", Command.CANCEL, 1);

    private ServiceList m_Services;

    private void onListItemSelected(List list) {
        int deviceIndex = list.getSelectedIndex();
        RemoteDevice device = (RemoteDevice)m_DeviceVector.elementAt(deviceIndex);

        Display disp = Display.getDisplay(m_Midlet);
        Displayable tmp = disp.getCurrent();
        m_Services = new ServiceList(m_Midlet, tmp, device);
        m_Services.discover();
    }

    private void onCancelSearch() {
        try {
            DiscoveryAgent discoveryAgent = LocalDevice.getLocalDevice().getDiscoveryAgent();
            discoveryAgent.cancelInquiry(this);
        }
        catch (BluetoothStateException ex) {
            m_Alert.display(ex.getMessage(), AlertType.ERROR, 5000);
        }
    }

    private void onCmdRetry() {
        discover();
    }

    private void onCmdExit() {
        m_Midlet.exit();
    }

    public void discover() {
        try {
            BusyAlert.show(m_Midlet, "Discovering Bluetooth devices", this, CMD_CANCEL);

            if (m_Devices != null) {
                m_Devices.deleteAll();
                m_DeviceVector.removeAllElements();
            }
            else {
                m_Devices = new List("Discovered Devices", List.IMPLICIT);
                m_Devices.addCommand(CMD_RETRY);
                m_Devices.addCommand(CMD_EXIT);
                m_Devices.setCommandListener(this);
                m_DeviceVector = new Vector();
            }

            LocalDevice localDevice = LocalDevice.getLocalDevice();
            DiscoveryAgent discoveryAgent = localDevice.getDiscoveryAgent();
            discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
        }
        catch (BluetoothStateException ex) {
            m_Alert.display("Bluetooth error: " + ex.getMessage(), AlertType.ERROR);
        }
    }

    private cx.ath.skyflyer.gpslog.ui.Alert m_Alert;
    private GpsLogMidlet m_Midlet;
    private List m_Devices;
    private Vector m_DeviceVector = new Vector();
    private Image m_BtLogo = null;
}
